package com.hang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hang.common.BizErrorCodeEnum;
import com.hang.common.BizException;
import com.hang.config.RedisConfig;
import com.hang.mapper.ClazzStudentMapper;
import com.hang.mapper.StudentMapper;
import com.hang.model.Clazz;
import com.hang.model.ClazzStudent;
import com.hang.model.Student;
import com.hang.service.ClazzService;
import com.hang.mapper.ClazzMapper;
import com.hang.vo.ClazzVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 */
@Service
public class ClazzServiceImpl extends ServiceImpl<ClazzMapper, Clazz>
    implements ClazzService{

    @Autowired
    private RedisConfig redisConfig;

    @Autowired
    private ClazzStudentMapper clazzStudentMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private ClazzMapper clazzMapper;

    @Override
    public void createClazz(ClazzVo clazzVo) {
        if(!ObjectUtils.isEmpty(clazzVo)){
            Clazz clazz = new Clazz();
            BeanUtils.copyProperties(clazzVo,clazz);
            baseMapper.insert(clazz);
        }
    }

    /**
     * 获取班级的详尽信息
     * @param clazzId
     * @return
     */
    @Override
    public Map<String,Object> detail(String clazzId) {
        if(ObjectUtils.isEmpty(clazzId)){
            throw new BizException(BizErrorCodeEnum.ID_IS_NULL);
        }

        QueryWrapper<Clazz> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("clazz_id",clazzId);
        Clazz clazz = baseMapper.selectOne(queryWrapper);

        if(ObjectUtils.isEmpty(clazz)){
            throw new BizException(BizErrorCodeEnum.CLAZZ_FOUND_FAIL);
        }

        RedisTemplate<String, Object> redisTemplate = redisConfig.getRedisTemplate();

        //先包装班级基本信息
        Map<String,Object> map = new HashMap<>();
        map.put("clazzName",clazz.getClazzName());
        map.put("times",clazz.getTimes());
        map.put("counts",clazz.getCounts());

        /**
         * 再封装所在班级的所有学生的信息
         *    - 先去redis中找是否有对应的clazzId
         *          如果有，则直接从缓存中取
         *          如果没有，则先从数据库中取，再写入缓存
         */
        List list = redisTemplate.opsForList().range(clazzId, 0, -1);
        List<String> students;
        if(list.size() == 0){
            //这个班级还没有存入相对应的数据，先存入
            students = new ArrayList<>();
        }else {
            students= (List<String>) list.get(0);
        }

        //临时学生列表
        List<Student> tmpStudents = new ArrayList<>();
        List<String> studentList = new ArrayList<>();

        if(ObjectUtils.isEmpty(students) || students.size() == 0){
            //说明在redis中没有此记录,去mysql中取
            QueryWrapper<ClazzStudent> wrapper = new QueryWrapper<>();
            wrapper.eq("clazz_id",clazzId);

            List<ClazzStudent> clazzStudents = clazzStudentMapper.selectList(wrapper);
            if(ObjectUtils.isEmpty(clazzStudents) || clazzStudents.size() == 0){
                //班级没有学生
                throw new BizException(BizErrorCodeEnum.STUDENT_IS_EMPTY);
            }

            //否则则读出学生列表中的相关信息，并且将学号写入到redis中
            for (ClazzStudent clazzStudent : clazzStudents){
                QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
                studentQueryWrapper.eq("student_id",clazzStudent.getStudentId());

                Student student = studentMapper.selectOne(studentQueryWrapper);

                studentList.add(clazzStudent.getStudentId());
                if(!ObjectUtils.isEmpty(student)){
                    tmpStudents.add(student);
                }
            }

            redisTemplate.opsForList().rightPush(clazzId,studentList);

        }else {
            //直接从缓存中取
            for(String stu_id : students){
                QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
                studentQueryWrapper.eq("student_id",stu_id);

                Student stu = studentMapper.selectOne(studentQueryWrapper);
                if(!ObjectUtils.isEmpty(stu)){
                    tmpStudents.add(stu);
                }
            }
        }

        map.put("students",tmpStudents);

        //返回结果集
        return map;
    }

    /**
     * 获取学生的课程数目
     * @param studentId
     * @return
     *
     * 这部分暂且未作性能优化，因为从clazz_student表读取的缘故，
     * 这张表数据量可能会很大，待后期维护时，若需要升级，可以考虑将
     * 学号作为key存储在redis中，后续从redis中读取以减轻对数据库的压力
     */
    @Override
    public Integer getClazzCount(String studentId) {
        QueryWrapper<ClazzStudent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("student_id",studentId);

        final Integer count = clazzStudentMapper.selectCount(queryWrapper);

        return count>0?count:0;
    }

    /**
     * 获取教师的课程数目
     * @param teacherId
     * @return
     */
    @Override
    public Integer getTeacherClazzCounts(String teacherId) {
        QueryWrapper<Clazz> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teacher_id",teacherId);

        Integer count = clazzMapper.selectCount(queryWrapper);
        return count>0?count:0;
    }
}